#pragma once
#include <deque>
#include <Ice\Config.h>
#include <IceUtil\Shared.h>
#include <IceUtil\Mutex.h>
#include <IceUtil\Monitor.h>

namespace Xts
{
	namespace Util
	{
		template<typename ItemType>
		class XThreadSafeQueue : public ::IceUtil::Monitor<::IceUtil::Mutex>, public ::IceUtil::Shared
		{
		public:
			XThreadSafeQueue(void);
			~XThreadSafeQueue(void);

			void Enqueue(const ItemType&);
			ItemType Dequeue(void);
			void Clear(void);

		protected:
			::std::deque<ItemType> x_itemQueue;
			::Ice::Short x_waitingReaders;
		};

		template<typename ItemType>
		XThreadSafeQueue<ItemType>::XThreadSafeQueue(void)
			:x_waitingReaders(0)
		{
		}

		template<typename ItemType>
		XThreadSafeQueue<ItemType>::~XThreadSafeQueue(void)
		{
			x_itemQueue.clear();
		}

		template<typename ItemType>
		void XThreadSafeQueue<ItemType>::Enqueue(const ItemType& item)
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);
			x_itemQueue.push_back(item);
			if (x_waitingReaders)
				notify();
		}

		template<typename ItemType>
		ItemType XThreadSafeQueue<ItemType>::Dequeue(void)
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);
			while (x_itemQueue.size() == 0)
			{
				try
				{
					++x_waitingReaders;
					wait();
					--x_waitingReaders;
				}
				catch (::std::exception ex)
				{
					--x_waitingReaders;
					throw;
				}
			}

			ItemType item = x_itemQueue.front();
			x_itemQueue.pop_front();
			return item;
		}

		template<typename ItemType>
		void XThreadSafeQueue<ItemType>::Clear(void)
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);
			x_itemQueue.clear();
		}
	}
}



